<?php

namespace app\utils;

class APKSigner{

    const KeystorePath = 'runtime/latest.keystore';
    const JKSPath = 'runtime/latest.jks';

    public static function signApkWithKeystore($apk_path, $alias, $password){
        return self::signApk(self::KeystorePath, $apk_path, $alias, $password);
    }

    public static function signApkWithJKS($apk_path, $alias, $password){
        return self::signApk(self::JKSPath, $apk_path, $alias, $password);
    }

    private static function signApk($key_path, $apk_path, $alias, $password){
        $apksigner = config('app.apksigner');
        $tempFilePath = 'runtime/temp.apk';
        if(file_exists($tempFilePath)){
            unlink($tempFilePath);
        }
        $command = "\"$apksigner\" sign --ks $key_path --ks-key-alias $alias --ks-pass pass:$password --ks-pass pass:$password --out $tempFilePath $apk_path";
        $output = null;
        $returnVar = null;
        exec($command, $output, $returnVar);
        if(file_exists($apk_path)){
            //unlink($apk_path);
        }
        if(file_exists($tempFilePath)){
            //rename($tempFilePath, $apk_path);
        }
        if($returnVar === 0){
            $outputStr = json_encode($output);
            return "Sign apk success: $outputStr\n";
        }else{
            return "Sign apk Error. Return code: $returnVar\n cmd: $command";
        }
    }

    public static function canCreateNewKeystore(){
        if(!file_exists(self::KeystorePath)){
            return true;
        }
        $fileCreationTime = filemtime(self::KeystorePath);
        $minutesOver = (time() - $fileCreationTime) / 60;
        if($minutesOver > 30){
            return true;
        }
        return false;
    }

    public static function createNewKeystore($alias, $password){
        return self::createNewKey('keystore', $alias, $password);
    }

    public static function createNewJKS($alias, $password){
        return self::createNewKey('jks', $alias, $password);
    }

    //$type: keystore 或者 jks
    private static function createNewKey($type, $alias, $password){
        if(strtolower($type) == 'keystore'){
            $key_path = self::KeystorePath;
            $typeStr = 'pkcs12';
        }else{
            $key_path = self::JKSPath;
            $typeStr = 'JKS';
        }
        $validity = 10000;
        $your_name = self::generateRandomString(10);
        $your_org_unit = self::generateRandomString(10);
        $your_org = self::generateRandomString(10);
        $your_city = self::generateRandomString(10);
        $your_state = self::generateRandomString(10);
        $your_country = self::generateRandomString(8);
        $keytool = config('app.keytool');
        $command =
            "\"$keytool\" -genkeypair -v -keystore $key_path -alias $alias -keyalg RSA -keysize 2048 -validity $validity -keypass $password -storepass $password -dname \"CN=$your_name, OU=$your_org_unit, O=$your_org, L=$your_city, S=$your_state, C=$your_country\" -storetype $typeStr";
        if(file_exists($key_path)){
            unlink($key_path);
        }
        $output = null;
        $returnVar = null;
        exec($command, $output, $returnVar);
        if($returnVar === 0){
            $outputStr = json_encode($output);
            return "Keystore create success: $outputStr\n";
        }else{
            return "Keystore create Error. Return code: $returnVar\n cmd: $command";
        }
    }

    public static function generateRandomString($length){
        if($length <= 0){
            return '';
        }
        $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for($i = 0; $i < $length; $i ++){
            $randomByte = random_int(0, $charactersLength - 1);
            $randomString .= $characters[$randomByte];
        }
        return $randomString;
    }

}